package tp.igl;

import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *<b> Adresse est la classe representant une Adresse réseau</b>
 * <p>
 *  Une adresse est caractérisé par quatre Octets chacun est représentés par un Segement.
 * Chaque Segement prend une valeur entre 0 et 255.
 * </p>
 * @author Redouane
 * @author PNR KACIMI HACINI
 * @see Segment
 */
public class Adresse {
    /**
     * un tableau de Segement pour contenir l'adresse
     */
    protected Segment adresse[];
       
    /**
     *Constructeur de la class Adresse
     * @param seg1  le segement a affecté dans la position 1
     * @param seg2  le segement a affecté dans la position 2
     * @param seg3  le segement a affecté dans la position 3
     * @param seg4  le segement a affecté dans la position 4
     */
    public Adresse(Segment seg1,Segment seg2,Segment seg3,Segment seg4){
        this.adresse=new Segment[]{seg1,seg2,seg3,seg4};
        
    }
    
    /**
     *recuperer l'adresse sous la forme d'un tableau
     * @return un tableau des segements qui represent l'adresse
     */
    public Segment[] getAdresse() {
        return adresse;
    }
    
    /**
     *Constructeur de la class Adresse
     * @param segments  le tableau de Segements pour initialiser l'adresse
     */
    public Adresse(Segment []segments){
        this.adresse=segments;
    }
    
    /**
     * Setter du champ adresse
     * @param adr
     */
    public void setAdresse(Adresse adr){
        this.getAdresse()[0].setValeur(adr.getAdresse()[0].getValeur());
        this.getAdresse()[1].setValeur(adr.getAdresse()[1].getValeur());
        this.getAdresse()[2].setValeur(adr.getAdresse()[2].getValeur());
        this.getAdresse()[3].setValeur(adr.getAdresse()[3].getValeur());
    }
    
  
     /**
     *Affecter une valeur a l'adress
     * @param adresse le tableau de segements a affecté
     */
    public void setAdresse(Segment[] adresse) {
        this.adresse = adresse;
    }
    
    
    /**
     *convertir l'adresse dans une des bases selon le parametre , et le renvoie 
     * sous la forme d'une chaine de caracteres
     * @param base  la base de convertion 8:Octal 10:Décimal  16:Hexdécimal
     * @return l'adresse aprés la conversion sous la forme d'une chaine de caracteres.
     */
    public String toString(int base){
            if (base==2) return adresse[0].toString(true)+adresse[1].toString(true)+adresse[2].toString(true)+adresse[3].toString(true);
            if (base==10) return adresse[0].toString()+"."+adresse[1].toString()+"."+adresse[2].toString()+"."+adresse[3].toString();
            if (base==8)  return Integer.toOctalString(adresse[0].getValeur())+"."+Integer.toOctalString(adresse[1].getValeur())+"."+Integer.toOctalString(adresse[2].getValeur())+"."+Integer.toOctalString(adresse[3].getValeur());
            if (base==16) return Integer.toHexString(adresse[0].getValeur())+"."+Integer.toHexString(adresse[1].getValeur())+"."+Integer.toHexString(adresse[2].getValeur())+"."+Integer.toHexString(adresse[3].getValeur());
                
            else return null;
        }
    /**
     * Renvoie le nombre de zero dans l'adresse quand elle est ecrite sous la forme binaire
     * @return nombre de Zero
     */
    public int getNbrDeZero(){
        return regexOccur(this.toString(2), Pattern.quote("0"));
    }
    
    /**
    * Renvoie le nombre d'occurrences du pattern spécifié dans la chaine de caractères spécifiée
    * @param text chaine de caractères initiale
    * @param regex expression régulière dont le nombre d'occurrences doit etre compté
    * @return le nombre d'occurrences du pattern spécifié dans la chaine de caractères spécifiée
    */
    public static int regexOccur(String text, String regex) {
       Matcher matcher = Pattern.compile(regex).matcher(text);
       int occur = 0;
       while(matcher.find()) {
           occur ++;
       }
       return occur;
   }
    
    /**
     * Redéfinition de la méthode equals pour l'utiliser dans les test unitaires (asserEquals)
     * @param obj
     * @return
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Adresse other = (Adresse) obj;
        Segment[] seg=this.adresse;
        for (int i=0;i<seg.length;i++)
            if (!seg[i].equals(other.getAdresse()[i])) {
                return false;
            }
        return true;
    }   

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 67 * hash + Arrays.deepHashCode(this.adresse);
        return hash;
    }
 }


